🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / takserver / src / commonTest / kotlin / org / meshtastic / core / takserver / MeshNodeCoTConversionTest.kt
Displaying Raw • Download
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/MeshNodeCoTConversionTest.kt 65a1f5ce4d0e4b8eafcd0bbfccafd41dc6ee888a (65a1f5ce) Text, 8.45 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.takserver
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertFalse
Tff7b72import T7ee787kotlin.test.assertNull
Tff7b72import T7ee787kotlin.test.assertTrue
Tff7b72import T7ee787kotlin.time.Duration.Companion.minutes
Tff7b72class T56d364MeshNodeCoTConversionTest Tb4b4b4{
Tf0883e@Test
Tff7b72fun Td2a8ff`eligible node passes the filter`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertTrueTb4b4b4(Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3isEligibleForCotTb4b4b4(Te6edf3ourNodeNum Tff7b72= Te6edf3OTHER_NODE_NUMTb4b4b4, Te6edf3lastHeardThreshold Tff7b72= Te6edf3STALE_THRESHOLDTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`own node is excluded`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertFalseTb4b4b4(Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3isEligibleForCotTb4b4b4(Te6edf3ourNodeNum Tff7b72= Te6edf3NODE_NUMTb4b4b4, Te6edf3lastHeardThreshold Tff7b72= Te6edf3STALE_THRESHOLDTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`node without user info is excluded`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3node Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3hwModel Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3HardwareModelTb4b4b4.Te6edf3UNSETTb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isEligibleForCotTb4b4b4(Te6edf3ourNodeNum Tff7b72= Te6edf3OTHER_NODE_NUMTb4b4b4, Te6edf3lastHeardThreshold Tff7b72= Te6edf3STALE_THRESHOLDTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`node heard outside the window is excluded`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3node Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3lastHeard Tff7b72= Te6edf3STALE_THRESHOLD Tff7b72- T79c0ff1Tb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isEligibleForCotTb4b4b4(Te6edf3ourNodeNum Tff7b72= Te6edf3OTHER_NODE_NUMTb4b4b4, Te6edf3lastHeardThreshold Tff7b72= Te6edf3STALE_THRESHOLDTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`node without a valid position is excluded`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3node Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3latitudeI Tff7b72= T79c0ff0Tb4b4b4, Te6edf3longitudeI Tff7b72= T79c0ff0Tb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isEligibleForCotTb4b4b4(Te6edf3ourNodeNum Tff7b72= Te6edf3OTHER_NODE_NUMTb4b4b4, Te6edf3lastHeardThreshold Tff7b72= Te6edf3STALE_THRESHOLDTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`uid is derived from the node number and stays stable`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// ATAK keys a contact by uid; a uid that drifts spawns duplicate markers.
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffMESHTASTIC-A1B2C3D4Ta5d6ff"Tb4b4b4, Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3cotUidTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3cotUidTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3meshNodeTb4b4b4(Te6edf3shortName Tff7b72= Ta5d6ff"Ta5d6ffDIFFTa5d6ff"Tb4b4b4, Te6edf3longName Tff7b72= Ta5d6ff"Ta5d6ffRenamedTa5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3cotUidTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`uid hex is upper-case and zero-padded to match Apple`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Apple formats "MESHTASTIC-%08X". ATAK compares uids case-sensitively, so lower-case hex
T8b949e// would make an Android-bridged node a separate contact from the same iOS-bridged node.
Tff7b72val Te6edf3uid Tff7b72= Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3cotUidTb4b4b4(Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3uidTb4b4b4.Te6edf3uppercaseTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3uidTb4b4b4)
T8b949e// Low node number must keep its leading zeros rather than collapsing to "MESHTASTIC-2A".
Tff7b72val Te6edf3lowNum Tff7b72= Te6edf3NodeTb4b4b4(Te6edf3num Tff7b72= T79c0ff0Te6edf3x2aTb4b4b4, Te6edf3user Tff7b72= Te6edf3userTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3position Tff7b72= Te6edf3positionTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3lastHeard Tff7b72= Te6edf3RECENT_LAST_HEARDTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffMESHTASTIC-0000002ATa5d6ff"Tb4b4b4, Te6edf3lowNumTb4b4b4.Te6edf3cotUidTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`callsign is short and long name joined`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffWOLF - Wolf Ridge RelayTa5d6ff"Tb4b4b4, Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3cotCallsignTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`callsign falls back when a name is missing`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffWOLFTa5d6ff"Tb4b4b4, Te6edf3meshNodeTb4b4b4(Te6edf3longName Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3cotCallsignTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffWolf Ridge RelayTa5d6ff"Tb4b4b4, Te6edf3meshNodeTb4b4b4(Te6edf3shortName Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3cotCallsignTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ff!a1b2c3d4Ta5d6ff"Tb4b4b4, Te6edf3meshNodeTb4b4b4(Te6edf3shortName Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3longName Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3cotCallsignTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`remarks carry the reported telemetry`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Labels, order, and precision match Apple's createCoTFromNode (voltage at two decimals,
T8b949e// everything else at one) so remarks read identically whichever phone bridged the node.
Tff7b72val Te6edf3remarks Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3voltage Tff7b72= T79c0ff3.95fTb4b4b4)Tb4b4b4.Te6edf3cotRemarksTb4b4b4(Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(
Ta5d6ff"Ta5d6ffBattery: 76% | Voltage: 3.95V | Chan Util: 12.5% | Air Util Tx: 4.2% | RSSI: -92 dBm | SNR: 8.5 dBTa5d6ff"Tb4b4b4,
Te6edf3remarksTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`remarks omit unreported telemetry rather than reporting zero`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// A missing reading must not render as "0" — zero is a real value for every one of these.
Tff7b72val Te6edf3node Tff7b72= Te6edf3NodeTb4b4b4(Te6edf3num Tff7b72= Te6edf3NODE_NUMTb4b4b4, Te6edf3user Tff7b72= Te6edf3userTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3position Tff7b72= Te6edf3positionTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3lastHeard Tff7b72= Te6edf3RECENT_LAST_HEARDTb4b4b4)
Te6edf3assertNullTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3cotRemarksTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`zero is preserved as a real telemetry reading`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3node Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3batteryLevel Tff7b72= T79c0ff0Tb4b4b4, Te6edf3voltage Tff7b72= T79c0ff0fTb4b4b4, Te6edf3channelUtilization Tff7b72= T79c0ff0fTb4b4b4, Te6edf3airUtilTx Tff7b72= T79c0ff0fTb4b4b4, Te6edf3snr Tff7b72= T79c0ff0fTb4b4b4, Te6edf3rssi Tff7b72= T79c0ff0Tb4b4b4)
T8b949e// Apple suppresses each of these at zero; this repo reports them, since 0 dB SNR / 0 dBm
T8b949e// RSSI are real measurements and 0% battery is the value an operator most needs to see.
Tff7b72val Te6edf3remarks Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3cotRemarksTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffBattery: 0%Ta5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffVoltage: 0.00VTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffChan Util: 0.0%Ta5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffAir Util Tx: 0.0%Ta5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffRSSI: 0 dBmTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffSNR: 0.0 dBTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`negative fractional readings keep their sign`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// -5 / 10 truncates to 0 in integer division; naive formatting rendered -0.5 as "0.5".
Tff7b72val Te6edf3remarks Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3snr Tff7b72= Tff7b72-T79c0ff0.5fTb4b4b4)Tb4b4b4.Te6edf3cotRemarksTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3remarksTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffSNR: -0.5 dBTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3remarksTb4b4b4)
Tff7b72val Te6edf3belowMinusOne Tff7b72= Te6edf3meshNodeTb4b4b4(Te6edf3snr Tff7b72= Tff7b72-T79c0ff1T79c0ff2.5fTb4b4b4)Tb4b4b4.Te6edf3cotRemarksTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3belowMinusOneTff7b72!!Tb4b4b4.Te6edf3containsTb4b4b4(Ta5d6ff"Ta5d6ffSNR: -12.5 dBTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3belowMinusOneTb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`cot event matches the cross-platform contract`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3cot Tff7b72= Te6edf3meshNodeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toCoTMessageTb4b4b4(Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffMESHTASTIC-A1B2C3D4Ta5d6ff"Tb4b4b4, Te6edf3cotTb4b4b4.Te6edf3uidTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DEFAULT_PLI_COT_TYPETb4b4b4, Te6edf3cotTb4b4b4.Te6edf3typeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Ta5d6ff"Ta5d6ffWOLF - Wolf Ridge RelayTa5d6ff"Tb4b4b4, Te6edf3cotTb4b4b4.Te6edf3contactTff7b72?.Te6edf3callsignTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3MESH_NODE_TAK_TEAMTb4b4b4, Te6edf3cotTb4b4b4.Te6edf3groupTff7b72?.Te6edf3nameTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DEFAULT_TAK_ROLE_NAMETb4b4b4, Te6edf3cotTb4b4b4.Te6edf3groupTff7b72?.Te6edf3roleTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff7T79c0ff6Tb4b4b4, Te6edf3cotTb4b4b4.Te6edf3statusTff7b72?.Te6edf3batteryTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3MESH_NODE_STALE_MINUTESTb4b4b4.Te6edf3minutesTb4b4b4, Te6edf3cotTb4b4b4.Te6edf3stale Tff7b72- Te6edf3cotTb4b4b4.Te6edf3timeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(T79c0ff3T79c0ff7.7749Tb4b4b4, Te6edf3cotTb4b4b4.Te6edf3latitudeTb4b4b4, Te6edf3absoluteTolerance Tff7b72= T79c0ff1e-6Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Tff7b72-T79c0ff1T79c0ff2T79c0ff2.4194Tb4b4b4, Te6edf3cotTb4b4b4.Te6edf3longitudeTb4b4b4, Te6edf3absoluteTolerance Tff7b72= T79c0ff1e-6Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3NODE_NUM Tff7b72= T79c0ff0Te6edf3xa1b2c3d4Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Tff7b72const Tff7b72val Te6edf3OTHER_NODE_NUM Tff7b72= T79c0ff0Te6edf3x11111111
Tff7b72const Tff7b72val Te6edf3STALE_THRESHOLD Tff7b72= T79c0ff1Te6edf3_000_000
Tff7b72const Tff7b72val Te6edf3RECENT_LAST_HEARD Tff7b72= Te6edf3STALE_THRESHOLD Tff7b72+ T79c0ff1Te6edf3_000
Tff7b72fun Td2a8ffuserTb4b4b4(
Te6edf3shortNameTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ffWOLFTa5d6ff"Tb4b4b4,
Te6edf3longNameTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ffWolf Ridge RelayTa5d6ff"Tb4b4b4,
Te6edf3hwModelTb4b4b4: Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3HardwareModel Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3HardwareModelTb4b4b4.Te6edf3TBEAMTb4b4b4,
Tb4b4b4) Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3UserTb4b4b4(
Te6edf3id Tff7b72= Ta5d6ff"Ta5d6ff!a1b2c3d4Ta5d6ff"Tb4b4b4,
Te6edf3short_name Tff7b72= Te6edf3shortNameTb4b4b4,
Te6edf3long_name Tff7b72= Te6edf3longNameTb4b4b4,
Te6edf3hw_model Tff7b72= Te6edf3hwModelTb4b4b4,
Tb4b4b4)
Tff7b72fun Td2a8ffpositionTb4b4b4(Te6edf3latitudeITb4b4b4: Tffa657Int Tff7b72= T79c0ff3T79c0ff7T79c0ff7Te6edf3_749_000Tb4b4b4, Te6edf3longitudeITb4b4b4: Tffa657Int Tff7b72= Tff7b72-T79c0ff1Te6edf3_224_194_000Tb4b4b4) Tff7b72=
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3PositionTb4b4b4(Te6edf3latitude_i Tff7b72= Te6edf3latitudeITb4b4b4, Te6edf3longitude_i Tff7b72= Te6edf3longitudeITb4b4b4)
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4)
Tff7b72fun Td2a8ffmeshNodeTb4b4b4(
Te6edf3shortNameTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ffWOLFTa5d6ff"Tb4b4b4,
Te6edf3longNameTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ffWolf Ridge RelayTa5d6ff"Tb4b4b4,
Te6edf3hwModelTb4b4b4: Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3HardwareModel Tff7b72= Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3HardwareModelTb4b4b4.Te6edf3TBEAMTb4b4b4,
Te6edf3latitudeITb4b4b4: Tffa657Int Tff7b72= T79c0ff3T79c0ff7T79c0ff7Te6edf3_749_000Tb4b4b4,
Te6edf3longitudeITb4b4b4: Tffa657Int Tff7b72= Tff7b72-T79c0ff1Te6edf3_224_194_000Tb4b4b4,
Te6edf3lastHeardTb4b4b4: Tffa657Int Tff7b72= Te6edf3RECENT_LAST_HEARDTb4b4b4,
Te6edf3snrTb4b4b4: Tffa657Float Tff7b72= T79c0ff8.5fTb4b4b4,
Te6edf3rssiTb4b4b4: Tffa657Int Tff7b72= Tff7b72-T79c0ff9T79c0ff2Tb4b4b4,
T8b949e// Exact tenths so NumberFormatter's rounding can't introduce ambiguity here —
T8b949e// rounding behavior itself belongs to NumberFormatterTest, not this class.
Te6edf3batteryLevelTb4b4b4: Tffa657Int Tff7b72= T79c0ff7T79c0ff6Tb4b4b4,
Te6edf3voltageTb4b4b4: Tffa657Float Tff7b72= T79c0ff3.9fTb4b4b4,
Te6edf3channelUtilizationTb4b4b4: Tffa657Float Tff7b72= T79c0ff1T79c0ff2.5fTb4b4b4,
Te6edf3airUtilTxTb4b4b4: Tffa657Float Tff7b72= T79c0ff4.2fTb4b4b4,
Tb4b4b4) Tff7b72=
Te6edf3NodeTb4b4b4(
Te6edf3num Tff7b72= Te6edf3NODE_NUMTb4b4b4,
Te6edf3user Tff7b72= Te6edf3userTb4b4b4(Te6edf3shortNameTb4b4b4, Te6edf3longNameTb4b4b4, Te6edf3hwModelTb4b4b4)Tb4b4b4,
Te6edf3position Tff7b72= Te6edf3positionTb4b4b4(Te6edf3latitudeITb4b4b4, Te6edf3longitudeITb4b4b4)Tb4b4b4,
Te6edf3lastHeard Tff7b72= Te6edf3lastHeardTb4b4b4,
Te6edf3snr Tff7b72= Te6edf3snrTb4b4b4,
Te6edf3rssi Tff7b72= Te6edf3rssiTb4b4b4,
Te6edf3deviceMetrics Tff7b72=
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3protoTb4b4b4.Te6edf3DeviceMetricsTb4b4b4(
Te6edf3battery_level Tff7b72= Te6edf3batteryLevelTb4b4b4,
Te6edf3voltage Tff7b72= Te6edf3voltageTb4b4b4,
Te6edf3channel_utilization Tff7b72= Te6edf3channelUtilizationTb4b4b4,
Te6edf3air_util_tx Tff7b72= Te6edf3airUtilTxTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.07s